// copy from vue
function getType(fn) {
  const match = fn && fn.toString().match(/^\s*function (\w+)/);
  return match ? match[1] : "";
}

function isSameType(a, b) {
  return getType(a) === getType(b);
}

function getTypeIndex(type, expectedTypes) {
  if (!Array.isArray(expectedTypes)) {
    return isSameType(expectedTypes, type) ? 0 : -1;
  }
  for (let i = 0, len = expectedTypes.length; i < len; i++) {
    if (isSameType(expectedTypes[i], type)) {
      return i;
    }
  }
  return -1;
}

/**
const fn = mergeWithRules({
  page: { type: Number, default: 1 },
  pageSize: { type: Number, default: 10 },
});

fn({ page: null, pageSize: "10" }) --> {page: 1, pageSize: 10}
 */
export function mergeWithRules(rules) {
  return obj => {
    if (obj == null) {
      return null;
    }
    const result = {};
    Object.keys(obj).forEach(key => {
      if (!obj.hasOwnProperty(key)) {
        return;
      }
      let value = obj[key];
      const rule = rules[key];
      if (rule == null) {
        result[key] = value;
        return;
      }
      if (value == null) {
        if (rule.default) {
          if (typeof rule.default === "function") {
            value = rule.default();
          } else {
            value = rule.default;
          }
        }
      } else if (rule.trans != null) {
        value = rule.trans(value);
      } else if (rule.type != null) {
        if (getTypeIndex(Boolean, rule.type) > -1) {
          if (value === "true") {
            value = true;
          } else if (value === "false") {
            value = false;
          } else {
            value = !!value;
          }
        } else if (getTypeIndex(Number, rule.type) > -1) {
          value = +value;
        } else if (getTypeIndex(String, rule.type) > -1) {
          value = value.toString();
        }
      }
      result[key] = value;
    });
    return result;
  };
}

// const fn = mergeWithRules({
//   page: { type: Boolean },
//   pageSize: { type: Number, default: 15 }
// });

// console.log(fn({ page: "false", pageSize: "10", other: "hello" }));
